package com.jingdianjichi.subject.application.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jingdianjichi.subject.application.handler.subject.SubjectTypeHandler;
import com.jingdianjichi.subject.application.handler.subject.SubjectTypeHandlerFactory;
import com.jingdianjichi.subject.application.service.SubjectInfoApplicationService;
import com.jingdianjichi.subject.application.convert.SubjectInfoBOConverter;
import com.jingdianjichi.subject.domain.entity.SubjectInfoBO;
import com.jingdianjichi.subject.infra.basic.entity.SubjectInfo;
import com.jingdianjichi.subject.infra.basic.entity.SubjectInfoEs;
import com.jingdianjichi.subject.infra.basic.entity.SubjectMapping;
import com.jingdianjichi.subject.infra.basic.service.SubjectInfoService;
import com.jingdianjichi.subject.infra.basic.service.SubjectLabelService;
import com.jingdianjichi.subject.infra.basic.service.SubjectMappingService;
import com.jingdinajichi.subject.common.enmus.IsDeleteCodeEnum;
import com.jingdinajichi.subject.common.entity.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zwy
 * @version 1.0
 * @description: SubjectInfoApplicationServiceImpl
 * @date 2025/10/4 14:38
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class SubjectInfoApplicationServiceImpl implements SubjectInfoApplicationService {

    @Resource
    private SubjectInfoService subjectInfoService;
    @Resource
    private SubjectTypeHandlerFactory subjectTypeHandlerFactory;
    @Resource
    private SubjectMappingService subjectMappingService;
    @Resource
    private SubjectLabelService subjectLabelService;
    /**
     * 新增题目
     * 1.插入subjectInfo表
     * 2.插入subjectMapping表
     * 3.插入subjectType表
     * @param subjectInfoBO
     */
    @Override
    public void add(SubjectInfoBO subjectInfoBO) {
        //假设我们都写在主流程里面
//判断type，单选的调用单选的service，多选的调用多选的
//一大堆的if
//上一个工厂+策略的形式
//一个工厂包含了4种类型，根据传入的type自动映射选择处理
        if(log.isInfoEnabled()){
            log.info("SubjectInfoApplicationServiceImpl.add.bo:{}",subjectInfoBO);
        }
        SubjectInfo subjectInfo = SubjectInfoBOConverter.INSTANCE
                .convertBoToInfo(subjectInfoBO);
//        插入题目 subjectInfo表
        subjectInfo.setIsDeleted(IsDeleteCodeEnum.NOT_DELETE_CODE_ENUM.getCode());
        subjectInfo =  subjectInfoService.insert(subjectInfo);
        subjectInfoBO.setId(subjectInfo.getId());
        List<SubjectMapping> mappingList = new ArrayList<>();
        subjectInfoBO.getSubjectCategoryIds().forEach(subjectCategoryId -> {
            subjectInfoBO.getSubjectLabelIds().forEach(subjectLabelId -> {
                //subjectMapping表插入
                SubjectMapping subjectMapping = new SubjectMapping();
                subjectMapping.setSubjectId(subjectInfoBO.getId());
                subjectMapping.setCategoryId(Long.valueOf(subjectCategoryId));
                subjectMapping.setLabelId(Long.valueOf(subjectLabelId));
                subjectMapping.setIsDeleted(IsDeleteCodeEnum.NOT_DELETE_CODE_ENUM.getCode());
                mappingList.add(subjectMapping);
            });
        });
        subjectMappingService.batchInsert(mappingList);
        //subjectMapping表插入
        SubjectTypeHandler subjectTypeHandler = subjectTypeHandlerFactory.getHandler(subjectInfoBO.getSubjectType());
        subjectTypeHandler.add(subjectInfoBO);



    }
    /**
     * 分页查询题目列表基于subjectInfoBO（继承pageInfo）
     * 将传入的subjectInfoBO转化为subjectInfo
     * 1.调用subjectMappingService查询出符合条件（主要是categoryId和labelId）的List<subjectId>
     * 2.调用subjectInfoService.querySubjectInfoNumBySubjectIds用subjectInfo和subjectIds，
     * 查询出满足条件的subjectInfo的数量
     *3. 基于查到subjectInfo的数量，和pageInfo的pageNum，pageSize，计算出offset和limit
     * 调用subjectInfoService.querySubjectInfosBySubjectIds 查询出List<subjectInfo>
     *
     * @return PageResult<SubjectInfoBO>
     * 注意！！！！！ 构建pageResult要先对pageNum和pageSize赋值 在赋值Total原因是setTotal
     * 方法会使用到pageNum和pageSize，
     *
     */
    @Override
    public PageResult<SubjectInfoBO> getSubjectPage(Integer pageNum, Integer pageSize, SubjectInfoBO subjectInfoBO) {
        // 1. 创建 MyBatis-Plus 的 Page 对象
        Page<SubjectInfo> page = new Page<>(pageNum, pageSize);
        SubjectInfo subjectInfo = SubjectInfoBOConverter.INSTANCE.convertBoToInfo(subjectInfoBO);

        // 2. 调用 infra 层，传入 Page 对象和查询条件
        // MyBatis-Plus 分页插件会自动执行两条SQL:
        //   - 一条 COUNT(*) 查询总数
        //   - 一条带 LIMIT 的分页查询
        page = subjectInfoService.queryPageByCondition(page, subjectInfo, subjectInfoBO.getCategoryId(), subjectInfoBO.getLabelId());

        // 3. 转换并封装返回结果
        PageResult<SubjectInfoBO> pageResult = new PageResult<>();
        pageResult.setPageNum((int) page.getCurrent());
        pageResult.setPageSize((int) page.getSize());
        pageResult.setTotal((int) page.getTotal());
        pageResult.setRecords(SubjectInfoBOConverter.INSTANCE.convertInfoListToInfoBOList(page.getRecords()));

        return pageResult;
    }


    /**
     * 基于id查询题目信息
     * 1.调用subjectInfoService.queryById查询出subjectInfo
     * 2.调用subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType())
     * 得到subjectTypeHandler
     * 3.调用subjectTypeHandler.get(subjectInfo.getId())
     * 得到subjectInfoBO
     * 4.返回subjectInfoBO
     * @param subjectInfoBO
     * @return SubjectInfoBO
     * @author zwy
     * **/

    @Override
    public SubjectInfoBO querySubjectInfo(SubjectInfoBO subjectInfoBO) {

        SubjectInfoEs subjectInfoEs = subjectInfoService.querySubjectInfoEsById(subjectInfoBO.getId());

        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBO.getId());
        subjectInfoBO = SubjectInfoBOConverter.INSTANCE.convertInfoToInfoBO(subjectInfo);
        subjectInfoBO.setLabelNames(subjectInfoEs.getLabelNames());
//        通过题目id查询单选题表
        SubjectTypeHandler subjectTypeHandler = subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());
        subjectInfoBO = subjectTypeHandler.query(subjectInfoBO);
        return subjectInfoBO;
    }

}
